package strategic_monitor

import (
	"context"
	"fmt"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/constants"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/utils"
	"git.myscrm.cn/golang/stark/v4"
	"gorm.io/gorm"
)

type strategicMonitorRepository struct {
}

func NewStrategicMonitorRepository() StrategicMonitorRepositoryIface {
	return &strategicMonitorRepository{}
}

func (r *strategicMonitorRepository) QueryStrategicBidList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicBid, error) {
	var result []*StrategicBid
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicBid{}.TableName())

	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("title like ? or company_name like ?", fmt.Sprintf("%%%s%%", keyword), fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("publish_date desc,id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) QueryStrategicWinbidList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicWinbid, error) {
	var result []*StrategicWinbid
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicWinbid{}.TableName())

	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("title like ? or company_name like ?", fmt.Sprintf("%%%s%%", keyword), fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("publish_date desc,id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) UpdateStrategicBid(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicBid{}.TableName())
	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("title like ? or company_name like ?", fmt.Sprintf("%%%s%%", keyword), fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) UpdateStrategicWinbid(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicWinbid{}.TableName())
	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("title like ? or company_name like ?", fmt.Sprintf("%%%s%%", keyword), fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) QueryStrategicBidAuditList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicBidAudit, error) {
	var result []*StrategicBidAudit
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidAudit{}.TableName())

	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("publish_date desc,id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) SaveStrategicBidAudit(ctx context.Context, data *StrategicBidAudit) (*StrategicBidAudit, error) {
	err := stark.MySQLConn.Get(ctx).Create(data).Error
	return data, err
}

func (r *strategicMonitorRepository) UpdateStrategicBidAudit(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidAudit{}.TableName())
	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) QueryStrategicBidCompanyList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicBidCompany, error) {
	var result []*StrategicBidCompany
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidCompany{}.TableName())

	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("company_name like ?", fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) SaveStrategicBidCompany(ctx context.Context, data *StrategicBidCompany) (*StrategicBidCompany, error) {
	err := stark.MySQLConn.Get(ctx).Create(data).Error
	return data, err
}

func (r *strategicMonitorRepository) UpdateStrategicBidCompany(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidCompany{}.TableName())
	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) CountBidCompanyByIndustryId(ctx context.Context, industryId int64) (int64, error) {
	db := stark.MySQLConn.Get(ctx)
	subSql := fmt.Sprintf("select distinct(organizing_code) from %s where id in ("+
		"select audit_id from %s where industry_id = %d and is_deleted = %d) and is_deleted = %d",
		StrategicBidAudit{}.TableName(), StrategicBidIndustry{}.TableName(), industryId, constants.IsDeletedFalse, constants.IsDeletedFalse)

	var count int64
	err := db.Table(StrategicBidCompany{}.TableName()).Where("is_deleted = ? and organizing_code in ("+subSql+")",
		constants.IsDeletedFalse).Count(&count).Error
	if err != nil {
		return 0, err
	}

	return count, nil
}

func (r *strategicMonitorRepository) QueryStrategicBidIndustryList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicBidIndustry, error) {
	var result []*StrategicBidIndustry
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidIndustry{}.TableName())

	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) SaveStrategicBidIndustry(ctx context.Context, data *StrategicBidIndustry) (*StrategicBidIndustry, error) {
	err := stark.MySQLConn.Get(ctx).Create(data).Error
	return data, err
}

func (r *strategicMonitorRepository) UpdateStrategicBidIndustry(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidIndustry{}.TableName())
	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) CountStrategicBidAuditByIndustryId(ctx context.Context, industryId int64) (int64, error) {
	db := stark.MySQLConn.Get(ctx)
	subSql := fmt.Sprintf("select audit_id from %s where industry_id = %d and is_deleted = %d",
		StrategicBidIndustry{}.TableName(), industryId, constants.IsDeletedFalse)

	var count int64
	err := db.Table(StrategicBidAudit{}.TableName()).Where("is_deleted = ? and id in ("+subSql+")",
		constants.IsDeletedFalse).Count(&count).Error
	if err != nil {
		return 0, err
	}

	return count, nil
}

func (r *strategicMonitorRepository) QueryStrategicBidCooperateCompanyList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicBidCooperateCompany, error) {
	var result []*StrategicBidCooperateCompany
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidCooperateCompany{}.TableName())

	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) SaveStrategicBidCooperateCompany(ctx context.Context, data *StrategicBidCooperateCompany) (*StrategicBidCooperateCompany, error) {
	err := stark.MySQLConn.Get(ctx).Create(data).Error
	return data, err
}

func (r *strategicMonitorRepository) UpdateStrategicBidCooperateCompany(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidCooperateCompany{}.TableName())
	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

// CountBidCompanyCooperate 获取甲方单位的合作企业数量
func (r *strategicMonitorRepository) CountBidCompanyCooperate(ctx context.Context, bidCompanyName, organizingCode string) (int64, error) {
	db := stark.MySQLConn.Get(ctx)
	subSql := ""
	if organizingCode != "" {
		subSql = fmt.Sprintf("select id from %s where %s = '%s' and is_deleted = %d", StrategicBidAudit{}.TableName(), "organizing_code", organizingCode, constants.IsDeletedFalse)
	} else if bidCompanyName != "" {
		subSql = fmt.Sprintf("select id from %s where %s = '%s' and is_deleted = %d", StrategicBidAudit{}.TableName(), "company_name", bidCompanyName, constants.IsDeletedFalse)
	}

	var count int64
	err := db.Table(StrategicBidCooperateCompany{}.TableName()).Where("is_deleted = ? and audit_id in ("+subSql+")",
		constants.IsDeletedFalse).Count(&count).Error
	if err != nil {
		return 0, err
	}

	return count, nil
}

// CountBidCompanyCooperateByIndustryId 根据品类id获取关联的合作单位数量(去重)
func (r *strategicMonitorRepository) CountBidCompanyCooperateByIndustryId(ctx context.Context, industryId int64) (int64, error) {
	db := stark.MySQLConn.Get(ctx)
	subSql := fmt.Sprintf("select audit_id from %s where industry_id = %d and is_deleted = %d",
		StrategicBidIndustry{}.TableName(), industryId, constants.IsDeletedFalse)

	var count int64
	err := db.Table(StrategicBidCooperateCompany{}.TableName()).Distinct("cooperate_company_name").Where("is_deleted = ? and audit_id in ("+subSql+")",
		constants.IsDeletedFalse).Count(&count).Error
	if err != nil {
		return 0, err
	}

	return count, nil
}

// GetBidCompanyCooperateByCompanyId 根据客户id获取关联的合作单位
func (r *strategicMonitorRepository) GetBidCompanyCooperateByCompanyId(ctx context.Context, companyId int64, pageInfo *utils.PageInfo) (int64, []*StrategicBidCooperateCompany, error) {
	var result []*StrategicBidCooperateCompany
	var count int64
	db := stark.MySQLConn.Get(ctx)
	db = db.Table(StrategicBidCooperateCompany{}.TableName()+" as a").
		Joins("left join "+StrategicBidAudit{}.TableName()+" as b on a.audit_id = b.id").
		Joins("left join "+StrategicBidCompany{}.TableName()+" as c on b.organizing_code = c.organizing_code").
		Where("a.is_deleted = ? and b.is_deleted = ? and c.is_deleted = ?", constants.IsDeletedFalse, constants.IsDeletedFalse, constants.IsDeletedFalse).
		Where("c.id = ?", companyId)

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Select("a.*").Order("a.id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) QueryStrategicIndustryList(ctx context.Context, condition map[string]interface{}, pageInfo *utils.PageInfo) (int64, []*StrategicIndustry, error) {
	var result []*StrategicIndustry
	var count int64
	db := stark.MySQLConn.Get(ctx).Table(StrategicIndustry{}.TableName())

	if condition != nil {
		if keyword, ok := condition["keyword"]; ok {
			db = db.Where("industry_name like ?", fmt.Sprintf("%%%s%%", keyword))
			delete(condition, "keyword")
		}
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}

	err := db.Count(&count).Error
	if err != nil {
		return 0, nil, err
	}

	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}

	err = db.Order("id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return 0, result, nil
		}
		return 0, nil, err
	}
	return count, result, nil
}

func (r *strategicMonitorRepository) SaveStrategicIndustry(ctx context.Context, data *StrategicIndustry) (*StrategicIndustry, error) {
	err := stark.MySQLConn.Get(ctx).Create(data).Error
	return data, err
}

func (r *strategicMonitorRepository) UpdateStrategicIndustry(ctx context.Context, condition, data map[string]interface{}) error {
	db := stark.MySQLConn.Get(ctx).Table(StrategicIndustry{}.TableName())
	if condition != nil {
		if len(condition) > 0 {
			db = db.Where(condition)
		}
	}
	return db.Updates(data).Error
}

func (r *strategicMonitorRepository) QueryStrategicIndustryByAuditId(ctx context.Context, auditId int64) ([]*StrategicIndustry, error) {
	var result []*StrategicIndustry
	db := stark.MySQLConn.Get(ctx).Table(StrategicBidIndustry{}.TableName()+" as a").
		Joins("left join "+StrategicIndustry{}.TableName()+" as b on a.industry_id = b.id").
		Where("a.audit_id = ? and a.is_deleted = ? and b.is_deleted = ?", auditId, constants.IsDeletedFalse, constants.IsDeletedFalse)

	err := db.Select("b.*").Order("b.id desc").Find(&result).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return result, nil
		}
		return nil, err
	}
	return result, nil
}

func (r *strategicMonitorRepository) QueryBidCompanyOrganizingCodeByIndustryName(ctx context.Context, industryName []string) ([]string, error) {
	var result []string

	db := stark.MySQLConn.Get(ctx)
	err := db.Table(StrategicBidCompany{}.TableName()+" as a").
		Joins("left join "+StrategicBidAudit{}.TableName()+" as b on a.organizing_code = b.organizing_code and b.is_deleted = ?", constants.IsDeletedFalse).
		Joins("left join "+StrategicBidIndustry{}.TableName()+" as c on b.id = c.audit_id and c.is_deleted = ?", constants.IsDeletedFalse).
		Where("c.industry_id in (select id from "+StrategicIndustry{}.TableName()+" where industry_name in (?) and audit_status = ? and is_deleted = ?)",
			industryName, constants.AuditStatusAudited, constants.IsDeletedFalse).
		Where("a.audit_status = ? and a.is_deleted = ?", constants.AuditStatusAudited, constants.IsDeletedFalse).
		Select("a.organizing_code").
		Group("a.organizing_code").
		Find(&result).Error
	if err != nil {
		return nil, err
	}

	return result, nil
}

func (r *strategicMonitorRepository) GetCooperateNameByBidCompanyAndIndustry(ctx context.Context, organizingCode string, industryNames []string, pageInfo *utils.PageInfo) ([]*BidCompanyCooperateBo, error) {
	var result []*BidCompanyCooperateBo
	db := stark.MySQLConn.Get(ctx)
	db = db.Table(StrategicBidCooperateCompany{}.TableName()+" as a").
		Joins("left join "+StrategicBidAudit{}.TableName()+" as b on a.audit_id = b.id and b.is_deleted = 0").
		Joins("left join "+StrategicBidIndustry{}.TableName()+" as c on b.id = c.audit_id and c.is_deleted = 0").
		Joins("left join "+StrategicIndustry{}.TableName()+" as d on c.industry_id = d.id and d.is_deleted = 0").
		Joins("left join "+StrategicBidCompany{}.TableName()+" as e on b.organizing_code=e.organizing_code and e.is_deleted = 0").
		Where("d.audit_status = ?  and e.organizing_code = ? and a.is_deleted = 0",
			constants.AuditStatusAudited, organizingCode)
	if len(industryNames) != 0 {
		db = db.Where("d.industry_name in (?)", industryNames)
	}

	db.Select("a.cooperate_company_name as cooperate_company_name,GROUP_CONCAT(distinct a.audit_id) as audit_ids ,GROUP_CONCAT(distinct d.industry_name) as industry_names,GROUP_CONCAT(distinct b.publish_date order by b.publish_date desc) as publish_dates").
		Group("a.cooperate_company_name")
	if pageInfo != nil && pageInfo.PageSize > 0 && pageInfo.Page > 0 {
		db = db.Offset((pageInfo.Page - 1) * pageInfo.PageSize).Limit(pageInfo.PageSize)
	}
	err := db.Find(&result).Error
	if err != nil {
		return nil, err
	}
	return result, nil
}
